package com.example.myapplication

import android.os.Bundle
import android.util.Log
import android.widget.EditText
import android.widget.Toast
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.background
import androidx.compose.foundation.border
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.foundation.text.selection.SelectionContainer
import androidx.compose.material.*
import androidx.compose.material.MaterialTheme.colors
import androidx.compose.runtime.*
import androidx.compose.runtime.snapshots.SnapshotStateList
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.shadow
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.font.Font
import androidx.compose.ui.text.font.FontStyle
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.input.ImeAction
import androidx.compose.ui.text.input.KeyboardCapitalization
import androidx.compose.ui.text.input.KeyboardType
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import com.example.myapplication.ui.theme.BtnBg
import com.example.myapplication.ui.theme.CalculatorBg
import com.example.myapplication.ui.theme.MyApplicationTheme
import com.example.myapplication.ui.theme.NumberBg
import net.objecthunter.exp4j.Expression
import net.objecthunter.exp4j.ExpressionBuilder

class CalculatorActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        // WindowCompat.setDecorFitsSystemWindows(window, false)
        setContent {
            MyApplicationTheme(false) {
                val formulaComponent = remember { mutableStateListOf("") }
                val onError = remember { mutableStateOf(false) }

                Surface(
                    modifier = Modifier.background(Color(R.color.m_white)),
                    color = CalculatorBg
                ) {
                    CalculatorView(formulaComponent, onError)
                }
            }
        }
    }
}

private var canAddPoint = true

// 计算器计算逻辑
@Composable
fun CalculatorView(formulaComponent: SnapshotStateList<String>, onError: MutableState<Boolean>) {

    var mTotalStr = remember {
        mutableStateOf("")
    }

    var formulaComponentNew = remember { mutableStateListOf("") }

    fun total(value: Any) {
        formulaComponentNew.clear()
        formulaComponent.add(value.toString())
        formulaComponentNew.add(getFormula(formulaComponent))
        // 解决精度丢失问题
        formulaComponentNew.add("×10/10")
        // 仿照原生安卓计算器，点击=号后，text不显示，在输入框中显示结果
        mTotalStr.value = ""
        try {
            val finalFormula = getFormula(formulaComponentNew).replace("√", "sqrt")
                .replace("×", "*")
                .replace("÷", "/")

            val e: Expression = ExpressionBuilder(finalFormula)
//                        .function(ln)
//                        .function(lg)
//                        .operator(factorial)
                .build()
            val result = e.evaluate().toString()
            if (result == "NaN") {
                onError.value = true
            }
//                    formulaComponent.clear()
//                    formulaComponent.add(result)
            mTotalStr.value = result
        } catch (e: Exception) {
            onError.value = true
            formulaComponent.clear()
            formulaComponent.add("Error!")
        }
    }

    val onClickListener: (value: Any) -> Unit = { value: Any ->
        Log.e(".===>click", value.toString())
        when (value) {
            "0" -> {
                total(value)
            }
            "1" -> {
                total(value)
            }
            "2" -> {
                total(value)
            }
            "3" -> {
                total(value)
            }
            "4" -> {
                total(value)
            }
            "5" -> {
                total(value)
            }
            "6" -> {
                total(value)
            }
            "7" -> {
                total(value)
            }
            "8" -> {
                total(value)
            }
            "9" -> {
                total(value)
            }
            "." -> {
                val lastStr =
                    getFormula(formulaComponent).substring(getFormula(formulaComponent).length - 1)
                if (lastStr != "0" &&
                    lastStr != "1" &&
                    lastStr != "2" &&
                    lastStr != "3" &&
                    lastStr != "4" &&
                    lastStr != "5" &&
                    lastStr != "6" &&
                    lastStr != "7" &&
                    lastStr != "8" &&
                    lastStr != "9"
                ) {
                } else {
                    Log.e("===>dian", canAddPoint.toString())
                    if (!canAddPoint) {
                        // 已经包含小数点
                        // 啥也不做
                    } else {
                        formulaComponent.add(value.toString())
                        canAddPoint = false
                    }
                }

            }
            "+" -> {
                formulaComponent.add(value.toString())
                canAddPoint = true
            }
            "-" -> {
                formulaComponent.add(value.toString())
                canAddPoint = true
            }
            "×" -> {
                formulaComponent.add(value.toString())
                canAddPoint = true
            }
            "÷" -> {
                formulaComponent.add(value.toString())
                canAddPoint = true
            }
            "＝" -> {
                mTotalStr.value = ""
                try {
                    // 精度丢失问题
                    formulaComponent.add("×10/10")
                    val finalFormula = getFormula(formulaComponent).replace("√", "sqrt")
                        .replace("×", "*")
                        .replace("÷", "/")

                    val e: Expression = ExpressionBuilder(finalFormula)
//                        .function(ln)
//                        .function(lg)
//                        .operator(factorial)
                        .build()
                    val result = e.evaluate().toString()
                    if (result == "NaN") {
                        onError.value = true
                    }
                    formulaComponent.clear()
                    formulaComponent.add(result)
                    // mTotalStr.value = result
                } catch (e: Exception) {
                    onError.value = true
                    formulaComponent.clear()
                    formulaComponent.add("Error!")
                }
            }
            "DEL" -> {
                // 移除最后一位
                var currentStr = getFormula(formulaComponent)
                Log.e("===>befor", currentStr)
                currentStr.let {
                    if (it.isNotEmpty()) {
                        val mStr = it.substring(0, currentStr.length - 1)
                        Log.e("===>split", mStr)
                        formulaComponent.clear()
                        formulaComponent.add(mStr)
                    }
                }

                if (getFormula(formulaComponent).isEmpty()) {
                    mTotalStr.value = ""
                    canAddPoint = true
                } else if (getFormula(formulaComponent)
                        .substring(getFormula(formulaComponent).length - 1) == "." ||
                    getFormula(formulaComponent)
                        .substring(getFormula(formulaComponent).length - 1) == "+" ||
                    getFormula(formulaComponent)
                        .substring(getFormula(formulaComponent).length - 1) == "-" ||
                    getFormula(formulaComponent)
                        .substring(getFormula(formulaComponent).length - 1) == "×" ||
                    getFormula(formulaComponent)
                        .substring(getFormula(formulaComponent).length - 1) == "÷"
                ) {
                    // 如果最后一位被移除后，是操作符号，啥都不做
                } else {
                    total("")
                }
            }
            "AC" -> {
                formulaComponent.clear()
                canAddPoint = true
            }
        }
    }

    Column() {
        Column(modifier = Modifier.weight(2f)) {
            SelectableText(
                formulaComponent = formulaComponent,
                onError = onError,
                modifier = Modifier
                    .weight(1f)
            )
            Text(
                text = mTotalStr.value,
                modifier = Modifier
                    .fillMaxWidth()
                    .padding(vertical = 5.dp)
                    .weight(1f),
                color = Color.White,
                fontSize = 28.sp,
                fontWeight = FontWeight.Bold,
                maxLines = 1,
                textAlign = TextAlign.Right
            )
        }
        Column(
            modifier = Modifier
                .weight(5f)
                .padding(start = 5.dp, top = 0.dp, end = 5.dp, bottom = 8.dp)
        ) {
            Row(
                modifier = Modifier
                    .weight(1f)
            ) {
                NumberButton(title = "AC", BtnBg, modifier = Modifier.weight(1f), onClickListener)
                NumberButton(title = "÷", BtnBg, modifier = Modifier.weight(1f), onClickListener)
            }
            Row(
                modifier = Modifier
                    .weight(1f)
            ) {
                NumberButton(title = "7", NumberBg, modifier = Modifier.weight(1f), onClickListener)
                NumberButton(title = "8", NumberBg, modifier = Modifier.weight(1f), onClickListener)
                NumberButton(title = "9", NumberBg, modifier = Modifier.weight(1f), onClickListener)
                NumberButton(title = "×", BtnBg, modifier = Modifier.weight(1f), onClickListener)
            }
            Row(
                modifier = Modifier
                    .weight(1f)
            ) {
                NumberButton(title = "4", NumberBg, modifier = Modifier.weight(1f), onClickListener)
                NumberButton(title = "5", NumberBg, modifier = Modifier.weight(1f), onClickListener)
                NumberButton(title = "6", NumberBg, modifier = Modifier.weight(1f), onClickListener)
                NumberButton(title = "-", BtnBg, modifier = Modifier.weight(1f), onClickListener)
            }
            Row(
                modifier = Modifier
                    .weight(1f)
            ) {
                NumberButton(title = "1", NumberBg, modifier = Modifier.weight(1f), onClickListener)
                NumberButton(title = "2", NumberBg, modifier = Modifier.weight(1f), onClickListener)
                NumberButton(title = "3", NumberBg, modifier = Modifier.weight(1f), onClickListener)
                NumberButton(title = "+", BtnBg, modifier = Modifier.weight(1f), onClickListener)
            }
            Row(
                modifier = Modifier
                    .weight(1f)
            ) {
                NumberButton(title = "0", NumberBg, modifier = Modifier.weight(1f), onClickListener)
                NumberButton(title = ".", NumberBg, modifier = Modifier.weight(1f), onClickListener)
                NumberButton(
                    title = "DEL",
                    NumberBg,
                    modifier = Modifier.weight(1f),
                    onClickListener
                )
                NumberButton(title = "＝", BtnBg, modifier = Modifier.weight(1f), onClickListener)
            }
        }
    }
}

@Preview
@Composable
fun PreviewCalculatorView() {
    val formulaComponent = remember { mutableStateListOf("") }
    val onError = remember { mutableStateOf(false) }
    CalculatorView(formulaComponent, onError)
}

// 计算器按钮
@Composable
private fun NumberButton(
    title: String,
    color: Color,
    modifier: Modifier = Modifier,
    onClick: (value: Any) -> Unit = {}
) {
    val context = LocalContext.current
    Button(
        onClick = {
            onClick(title)
        },
        colors = ButtonDefaults.buttonColors(
            backgroundColor = color,
            contentColor = Color.White,
            disabledBackgroundColor = Color.Transparent,
            disabledContentColor = Color.White
        ),
        modifier = modifier
            .padding(horizontal = 3.dp, vertical = 3.dp)
            .fillMaxHeight(),
        shape = RoundedCornerShape(10.dp),
    ) {
        Text(
            text = title,
            modifier = Modifier.padding(0.dp),
            fontSize = 21.sp,
            fontWeight = FontWeight.Bold,
            textAlign = TextAlign.Center,
        )
    }
}

// 数学式
@Composable
fun SelectableText(
    modifier: Modifier = Modifier,
    formulaComponent: SnapshotStateList<String>,
    onError: MutableState<Boolean>,
) {
    SelectionContainer {
        TextField(
            value = getFormula(formulaComponent),
            onValueChange = { },
            maxLines = 3,
            textStyle = TextStyle(
                color = if (onError.value) {
                    Color.White
                } else {
                    Color.White
                },
                fontSize = 35.sp,
                textAlign = TextAlign.End,
            ),
            readOnly = true,
            isError = onError.value,
            keyboardOptions = KeyboardOptions(
                capitalization = KeyboardCapitalization.Sentences,
                autoCorrect = false,
                keyboardType = KeyboardType.Decimal,
                imeAction = ImeAction.None
            ),
            modifier = modifier
                .padding(3.dp)
                .fillMaxWidth()
        )
    }
}

fun getFormula(formulaComponent: SnapshotStateList<String>): String {
    if (formulaComponent.size <= 0) {
        return ""
    }
    val builder = StringBuilder("")
    for (str in formulaComponent) {
        builder.append(str)
    }
    Log.e("===>getFormula", builder.toString())
    return builder.toString()
}